import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:dartssh2/dartssh2.dart';
import 'package:uuid/uuid.dart';
import '../models/command_history.dart';
import '../models/ssh_connection.dart';
import 'database_service.dart';

class SSHService {
  final _uuid = const Uuid();
  SSHClient? _currentClient;
  SSHSession? _currentSession;
  
  SSHConnection? _currentConnection;
  
  SSHClient? get currentClient => _currentClient;
  SSHConnection? get currentConnection => _currentConnection;

  // 连接到SSH服务器
  Future<bool> connect(SSHConnection connection) async {
    try {
      final socket = await SSHSocket.connect(connection.host, connection.port);
      
      SSHKeyPair? keyPair;
      if (connection.privateKeyPath != null) {
        final privateKey = File(connection.privateKeyPath!).readAsStringSync();
        keyPair = SSHKeyPair.fromPem(privateKey, connection.passphrase).first;
      }

      _currentClient = SSHClient(
        socket,
        username: connection.username,
        onPasswordRequest: () => connection.password ?? '',
        identities: keyPair != null ? [keyPair] : null,
      );

      // 测试连接
      final session = await _currentClient!.execute('echo "Connection test"');
      await session.done;
      
      _currentConnection = connection;
      return true;
    } catch (e) {
      print('SSH连接失败: $e');
      return false;
    }
  }

  // 执行命令
  Future<CommandHistory> executeCommand(
    String command, {
    Duration timeout = const Duration(seconds: 30),
  }) async {
    if (_currentClient == null || _currentConnection == null) {
      throw Exception('未连接到SSH服务器');
    }

    final id = _uuid.v4();
    final startTime = DateTime.now();
    
    try {
      _currentSession = await _currentClient!.execute(command);
      
      final stdout = StringBuffer();
      final stderr = StringBuffer();
      
      // 监听输出流
      final stdoutSub = _currentSession!.stdout.listen((data) {
        stdout.write(String.fromCharCodes(data));
      });
      
      final stderrSub = _currentSession!.stderr.listen((data) {
        stderr.write(String.fromCharCodes(data));
      });

      // 等待命令完成并获取退出码
      final exitCode = await _currentSession!.done.timeout(timeout);
      
      // 确保所有输出都已接收
      await stdoutSub.cancel();
      await stderrSub.cancel();
      
      final output = stdout.toString();
      final errorOutput = stderr.toString();
      final fullOutput = output + (errorOutput.isNotEmpty ? '\n$stderr' : '');

      final history = CommandHistory(
        id: id,
        connectionId: _currentConnection!.id,
        command: command,
        executedAt: startTime,
        output: fullOutput,
        exitCode: 0,
      );

      return history;
    } catch (e) {
      return CommandHistory(
        id: id,
        connectionId: _currentConnection!.id,
        command: command,
        executedAt: startTime,
        output: '执行失败: $e',
        exitCode: -1,
      );
    }
  }

  // 执行脚本
  Future<List<CommandHistory>> executeScript(
    List<String> commands, {
    Duration timeout = const Duration(seconds: 30),
  }) async {
    final results = <CommandHistory>[];
    
    for (final command in commands) {
      if (command.trim().isEmpty) continue;
      
      final result = await executeCommand(command, timeout: timeout);
      results.add(result);
      
      // 如果命令失败，停止执行后续命令
      if (result.exitCode != 0) {
        break;
      }
    }
    
    return results;
  }

  // 上传文件
  Future<void> uploadFile(String localPath, String remotePath) async {
    if (_currentClient == null) {
      throw Exception('未连接到SSH服务器');
    }

    final file = File(localPath);
    if (!file.existsSync()) {
      throw Exception('本地文件不存在: $localPath');
    }

    final sftp = await _currentClient!.sftp();
    final fileData = file.readAsBytes();
    
    final remoteFile = await sftp.open(remotePath,
        mode: SftpFileOpenMode.create | SftpFileOpenMode.write);
    await remoteFile.write(fileData.asStream());
    await remoteFile.close();
  }

  // 下载文件
  Future<void> downloadFile(String remotePath, String localPath) async {
    if (_currentClient == null) {
      throw Exception('未连接到SSH服务器');
    }

    final sftp = await _currentClient!.sftp();
    final remoteFile = await sftp.open(remotePath);
    
    final fileData = await remoteFile.readBytes();
    final localFile = File(localPath);
    await localFile.writeAsBytes(fileData);
  }

  // 断开连接
  Future<void> disconnect() async {
    _currentSession?.close();
    _currentClient?.close();
    _currentClient = null;
    _currentSession = null;
    _currentConnection = null;
  }

  // 检查连接状态
  bool get isConnected => _currentClient != null;
}

// 在SSHService类中添加以下方法
extension SSHServiceExtension on SSHService {
  Future<bool> startShell({
    required Function(String) onOutput,
  }) async {
    if (_currentClient == null) return false;
    
    try {
      _currentSession = await _currentClient!.shell(
        pty: const SSHPtyConfig(
          type: 'xterm-256color',
          width: 80,
          height: 24,
        ),
      );
      
      _currentSession!.stdout.listen(
        (data) => onOutput(utf8.decode(data)),
        onError: (error) => onOutput('错误: $error'),
      );
      
      _currentSession!.stderr.listen(
        (data) => onOutput(utf8.decode(data)),
      );
      
      return true;
    } catch (e) {
      return false;
    }
  }

  Future<bool> writeToShell(String command) async {
    if (_currentSession == null) return false;
    
    try {
      _currentSession!.write(utf8.encode(command + '\n'));
      return true;
    } catch (e) {
      return false;
    }
  }
}